﻿using Engine;
using Engine.Graphics;
using Scenario_Editor;
using Scenario_Editor.AddinManager;
using Scenario_Editor.Tools;
using SharpDX;
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace WorldRacing2
{
    partial class GameDllScenarioEditor : Scenario_Editor.AddinManager.IAddinScenarioEditor
    {
        #region Private Fields

        private WorldRacing2.Exporter.ExportWindow exportWindow;
        private System.Windows.Forms.FolderBrowserDialog folderBrowserLoadWR2;
        private ToolStripButton toolStripButton_Material;
        private ToolStripButton toolStripButton_VertexColor;

        #endregion Private Fields

        #region Public Properties

        public object EnumGlobalShader { get; private set; }

        public Scenario_Editor.AddinManager.IExporter Exporter
        {
            get
            {
                throw new System.NotImplementedException();
            }
            set
            {
                throw new System.NotImplementedException();
            }
        }

        public Scenario_Editor.AddinManager.ITerrainPaintingControl TerrainPaintingControl
        {
            get
            {
                return (Scenario_Editor.AddinManager.ITerrainPaintingControl)this._terrainPaintingControl;
            }
            set
            {
                throw new System.NotImplementedException();
            }
        }

        #endregion Public Properties

        #region Public Methods

        public void AutomaticTextureing(ITerrain terrain)
        {
            Color4 color = new Color4()
            {
                Alpha = 0.0f,
                Blue = 0.6f,
                Green = 0.0f,
                Red = 0.0f
            };
            Color4 color2 = new Color4
            {
                Alpha = 0.0f,
                Blue = 0.45f,
                Green = 0.0f,
                Red = 0.0f
            };
            Color4 colorEdge = new Color4
            {
                Alpha = 0.0f,
                Blue = 0.0f,
                Green = 0.5f,
                Red = 0.5f
            };

            List<System.Drawing.Point> coordinatesForSmoothing = new List<System.Drawing.Point>();
            for (int x = 0; x < terrain.nSectorsX * terrain.numberOfCellsPerSector; x++)
            {
                for (int y = 0; y < terrain.nSectorsY * terrain.numberOfCellsPerSector; y++)
                {
                    bool isVertexColourChanged = true;

                    for (int i = 0; i < terrain.Cells[x, y].NormalForEachPolygon.Length; i++)
                    {
                        MyOwnVertex.Wr2Data vertex = (MyOwnVertex.Wr2Data)terrain.GetGameVertex(x, y);
                        vertex.VertexColor = color2;

                        if (Vector3.Dot(terrain.Cells[x, y].NormalForEachPolygon[i], Vector3.Up) < 0.85f)
                        {
                            var colortemp = vertex.VertexColor;
                            colortemp.Blue = color.Blue;

                            vertex.VertexColor = colortemp;// new Color4(0.0f, 0.0f, 0.0f, 1.0f - this.cells[x, y].Vertices[i].Normal.Y);// color;
                            isVertexColourChanged = true;
                        }
                        //else
                        //    this.vertices[x, y].vertexColor = color2;

                        // harte Kanten
                        for (int j = 0; j < terrain.Cells[x, y].Vertices.Count; j++)
                        {
                            if (Math.Abs(Vector3.Dot(terrain.Cells[x, y].Vertices[j].Normal, terrain.Cells[x, y].NormalForEachPolygon[i])) < 0.98f)
                            {
                                vertex.VertexColor += Color4.Scale(colorEdge, 1.0f / (float)terrain.Cells[x, y].NormalForEachPolygon.Length);// new Color4(0.0f, 0.0f, 0.0f, 1.0f - this.cells[x, y].Vertices[i].Normal.Y);// color;
                                isVertexColourChanged = true;
                            }
                        }

                        //for (int j = 0; j < this.cells[x, y].Vertices.Count; j++)
                        //{
                        //    float colorReg = -(Vector3.Dot(this.cells[x, y].Vertices[j].Normal, this.cells[x, y].NormalForEachPolygon[i])) + 1.2f;
                        //    this.vertices[x, y].vertexColor.Red = colorReg;// new Color4(0.0f, 0.0f, 0.0f, 1.0f - this.cells[x, y].Vertices[i].Normal.Y);// color;
                        //    this.vertices[x, y].vertexColor.Green = colorReg;// new Color4(0.0f, 0.0f, 0.0f, 1.0f - this.cells[x, y].Vertices[i].Normal.Y);// color;
                        //    this.vertices[x, y].vertexColor.Blue = 0;// new Color4(0.0f, 0.0f, 0.0f, 1.0f - this.cells[x, y].Vertices[i].Normal.Y);// color;
                        //        isVertexColourChanged = true;
                        //
                        //}

                        terrain.SetGameVertex(x, y, vertex);
                    }

                    if (isVertexColourChanged)
                    {
                        System.Drawing.Point cellCoordinate = new System.Drawing.Point(x, y);
                        System.Drawing.Point sectorCoordinate = terrain.GetSectorCoordinateFromCellCoordinate(cellCoordinate);
                        terrain.SetCoordinateForUpdates(sectorCoordinate.X, sectorCoordinate.Y, cellCoordinate);
                    }
                    coordinatesForSmoothing.Add(new System.Drawing.Point(x, y));
                }
            }

            SmoothVertexColor(terrain, Vector3.Zero, coordinatesForSmoothing, (int)Math.Max(terrain.nSectorsX * terrain.SECTORSIZE1, terrain.nSectorsY * terrain.SECTORSIZE1), 100);
        }

        public void ExportScenario(ScenarioFile scenarioFile)
        {
            if (this.exportWindow == null)
                this.exportWindow = new WorldRacing2.Exporter.ExportWindow(this.configurationDialog.ConfigurationData);
            if (!Directory.Exists(WorldRacing2.Configuration.WorldRacing2Addin.Default.WorldRacing2Folder))
            {
                MessageBox.Show("Please set World Racing 2 folder");
                this.configurationDialog.ShowDialog();
            }
            if (Directory.Exists(WorldRacing2.Configuration.WorldRacing2Addin.Default.WorldRacing2Folder))
            {
                this.exportWindow.SetVariables(scenarioFile, WorldRacing2.Configuration.WorldRacing2Addin.Default.WorldRacing2Folder);
                this.exportWindow.ShowDialog();
            }
            else
                MessageBox.Show("No World Racing 2 foler is set.");
        }

        public string GetGameName()
        {
            return "World Racing 2";
        }

        public Scenario_Editor.AddinManager.IMaterialEditorControl GetNewMaterialEditControl()
        {
            var newMaterialEditControl = new Material.MaterialEditUI();
            newMaterialEditControl.SetMaterialManager(this.materialManager, null);
            this._materialEditControl.Add(newMaterialEditControl);

            return newMaterialEditControl;
        }

        public ToolStripButton[] GetToolstripbuttonRendermodes()
        {
            this.toolStripButton_VertexColor = new System.Windows.Forms.ToolStripButton();
            this.toolStripButton_Material = new System.Windows.Forms.ToolStripButton();

            //
            // toolStripButton_VertexColor
            //
            this.toolStripButton_VertexColor.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
            this.toolStripButton_VertexColor.Image = Properties.Resources.VertexColor;
            this.toolStripButton_VertexColor.ImageTransparentColor = System.Drawing.Color.Magenta;
            this.toolStripButton_VertexColor.Name = "toolStripButton_VertexColor";
            this.toolStripButton_VertexColor.Size = new System.Drawing.Size(36, 36);
            this.toolStripButton_VertexColor.Text = "Shows the VertexColor";
            this.toolStripButton_VertexColor.Click += new System.EventHandler(OnChangeShaderToVertexColor);
            //
            // toolStripButton_Material
            //
            this.toolStripButton_Material.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
            this.toolStripButton_Material.Image = Properties.Resources.Material;
            this.toolStripButton_Material.ImageTransparentColor = System.Drawing.Color.Magenta;
            this.toolStripButton_Material.Name = "toolStripButton_Material";
            this.toolStripButton_Material.Size = new System.Drawing.Size(36, 36);
            this.toolStripButton_Material.Text = "Render with materials";
            this.toolStripButton_Material.Click += new System.EventHandler(OnChangeShaderToMaterials);

            ToolStripButton[] buttons = new ToolStripButton[]
                {
                    this.toolStripButton_VertexColor,
                    this.toolStripButton_Material
                };

            return buttons;
        }

        public ToolStripMenuItem GetToolstripitems()
        {
            ToolStripMenuItem root = new ToolStripMenuItem("World Racing 2");

            // Configuration Window
            ToolStripMenuItem configuration = new ToolStripMenuItem();
            configuration.Name = "configuration";
            configuration.Size = new System.Drawing.Size(330, 50);
            configuration.Text = "Config World Racing 2 Addin";
            configuration.Click += Configuration_Click;

            root.DropDownItems.AddRange(new ToolStripItem[]
                {
                  configuration
                });

            root.DropDownItems.AddRange(this.terrainToolstrip.GetToolstripItems());

            return root;
        }

        public void ImportTexturesFromGame(string sceneryEditorTextureFolder)
        {
            this.configurationDialog.ImportTexturesFromGame(sceneryEditorTextureFolder);
        }

        public ISceneryExtractor LoadScenery(Engine.Engine engine, ShaderManager shaderManager, Engine.Camera.Camera camera)
        {
            if (this.folderBrowserLoadWR2 == null)
                this.folderBrowserLoadWR2 = new FolderBrowserDialog();

            //if (Directory.Exists(@"E:\Games\World Racing 2\Scenarios\Italien"))
            //    this.folderBrowserLoadWR2.SelectedPath = @"E:\Games\World Racing 2\Scenarios\Italien";
            if (Directory.Exists(@"d:\Games\World Racing 2\Scenarios\Italien"))
                this.folderBrowserLoadWR2.SelectedPath = @"d:\Games\World Racing 2\Scenarios\Italien";

            if (DialogResult.OK == this.folderBrowserLoadWR2.ShowDialog())
            {
                Scenario.Wr2Scenario scenery = new Scenario.Wr2Scenario(this.folderBrowserLoadWR2.SelectedPath, engine, shaderManager, camera, 5000.0f);
                return scenery;
            }

            throw new Exception("No Scenery loaded!");
        }

        public void OnMaterialMangerChanged(object materialManager, System.EventArgs eventArgs)
        {
            this.materialManager = materialManager;
            this._terrainPaintingControl.MaterialManagerChanged(materialManager, eventArgs);
            this.configurationDialog.OnMaterialEditorChange(materialManager, eventArgs);
        }

        public void OnTerrainChanged(object sender, System.EventArgs e)
        {
            this._terrainPaintingControl.Terrain = (Scenario_Editor.Tools.Terrain.Terrain)sender;
            this.Terrain = (Scenario_Editor.Tools.Terrain.Terrain)sender;
            this.terrainToolstrip.Terrain = this.Terrain;
        }

        public IGameVertex PaintVertex(IGameVertex originalVertexData, IGameVertex newVertexData)
        {
            // Don´t change texturecoordinates or other things but vertexcolor.
            MyOwnVertex.Wr2Data returnVertex = (MyOwnVertex.Wr2Data)originalVertexData;
            returnVertex.VertexColor = ((MyOwnVertex.Wr2Data)newVertexData).VertexColor;
            return returnVertex;
        }

        private void OnChangeShaderToMaterials(object sender, EventArgs e)
        {
            GameDll.shaderArray.GlobalShader = WorldRacing2.Shaders.EnumGlobalShader.Material;
        }

        private void OnChangeShaderToVertexColor(object sender, EventArgs e)
        {
            GameDll.shaderArray.GlobalShader = WorldRacing2.Shaders.EnumGlobalShader.VertexColor;
        }

        #endregion Public Methods

        #region Private Methods

        private void LoadWR2SampleScenario(string selectedPath, object camera1)
        {
            //if (Directory.Exists(folderName))
            //{
            //    this.engineComplete.Grafic.RemoveRenderableObject(wr2Scenario);
            //    wr2Scenario = new Engine.FileFormats3D.Wr2Scenario(folderName, this.engineComplete, this.shaderManager, camera, this.ViewDistance);
            //    this.engineComplete.Grafic.AddRenderableObjects(wr2Scenario, 10);
            //    this.materialListUI.SetMaterialManager(wr2Scenario.MaterialManager, null);

            //    this.objectManager.objectFolder = folderName + "\\V1\\Objects\\";
            //    this.objectManager.TextureManager.TextureFolder = folderName + "\\V1\\Objects\\Textures\\";

            //    for (int i = 0; i < wr2Scenario.QadFile.objects.Count; i++)
            //    {
            //        Vector3 position = new Vector3(wr2Scenario.QadFile.objects[i].PositionX, wr2Scenario.QadFile.objects[i].PositionY, wr2Scenario.QadFile.objects[i].PositionZ);
            //        string fileName = string.Empty;

            //        if (wr2Scenario.QadFile.objects[i].Name.Contains("T\\"))
            //            fileName = wr2Scenario.QadFile.objects[i].Name.Substring(2, wr2Scenario.QadFile.objects[i].Name.Length - 2) + ".TREE";
            //        if (!wr2Scenario.QadFile.objects[i].Name.Contains("T\\"))
            //            fileName = wr2Scenario.QadFile.objects[i].Name + ".mox";

            //        Engine.ObjectManager.BaseNode baseNode = new Engine.ObjectManager.BaseNode(this.engineComplete, position);
            //        baseNode.Properties = (string)fileName;

            //        try
            //        {
            //            this.objectManager.AddObject(baseNode, wr2Scenario.QadFile.objects[i].AngleY, wr2Scenario.QadFile.objects[i].Size);
            //        }
            //        catch (FileNotFoundException e)
            //        {
            //            Console.WriteLine(e.Source);
            //        }
            //    }

            //    this.engineComplete.Grafic.RemoveRenderableObject(this.objectManager);
            //    this.engineComplete.Grafic.AddRenderableObjects(this.objectManager, 10);
            //}
        }

        private void SmoothVertexColor(ITerrain terrain, Vector3 positionOfBrush, List<System.Drawing.Point> cellsWhichShouldSmooth, int radius, int strengthPercent)
        {
            List<Color4> newColors = new List<Color4>();
            List<bool> shouldUpdateColor = new List<bool>();

            for (int i = 0; i < cellsWhichShouldSmooth.Count; i++)
            {
                System.Drawing.Point coordinate = cellsWhichShouldSmooth[i];
                int vX = coordinate.X;
                int vY = coordinate.Y;

                if (vX < 1 || vX >= terrain.nSectorsX * terrain.numberOfCellsPerSector ||
                vY < 1 || vY >= terrain.nSectorsY * terrain.numberOfCellsPerSector)
                {
                    shouldUpdateColor.Add(false);
                    continue;
                }

                float distance = GeoMath.DistancePlanar(terrain.Vertices[vX, vY].Position, positionOfBrush);
                if (distance < radius)
                {
                    Vector4 allheight = Vector4.Zero;
                    for (int x = -1; x < 2; x++)
                    {
                        for (int y = -1; y < 2; y++)
                        {
                            allheight += ((MyOwnVertex.Wr2Data)terrain.GetGameVertex(vX - x, vY - y)).VertexColor.ToVector4();
                        }
                    }
                    //Vector4 allheight = verticesWr2Data[vX, vY].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX - 1, vY - 1].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX, vY - 1].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX + 1, vY - 1].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX - 1, vY].VertexColor.ToVector4();
                    ////allheight += vertices[vX, vY].Y;
                    //allheight += verticesWr2Data[vX + 1, vY].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX - 1, vY + 1].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX, vY + 1].VertexColor.ToVector4();
                    //allheight += verticesWr2Data[vX + 1, vY + 1].VertexColor.ToVector4();
                    allheight /= 9;

                    shouldUpdateColor.Add(true);
                    newColors.Add(new Color4(((MyOwnVertex.Wr2Data)terrain.GetGameVertex(vX, vY)).VertexColor.ToVector4() + (allheight - ((MyOwnVertex.Wr2Data)terrain.GetGameVertex(vX, vY)).VertexColor.ToVector4()) * (strengthPercent / 100.0f)));
                }
                else
                    shouldUpdateColor.Add(false);
            }
            int currentColorIndex = 0;
            for (int i = 0; i < cellsWhichShouldSmooth.Count; i++)
            {
                System.Drawing.Point coordinate = cellsWhichShouldSmooth[i];
                int vX = coordinate.X;
                int vY = coordinate.Y;

                if (shouldUpdateColor[i])
                {
                    terrain.SetGameVertex(
                        new System.Drawing.Point(vX, vY),
                        new MyOwnVertex.Wr2Data() { VertexColor = newColors[currentColorIndex] },
                        terrain.AddinScenarioEditor);
                    //vertices[vX, vY].VertexColor = newColors[currentColorIndex];
                    currentColorIndex++;
                }
            }
        }

        #endregion Private Methods
    }
}